from tkinter import *
import sympy as sy
import numpy as np
from math import *
import turtle  as tt    #导入turtle模块



#创建主窗口
C12 = Tk()                                                           #创建主窗口
C12.title('信号与系统第十二章')                                      #主窗口标题
                                                                     #主窗口大小

#定义处理函数
def b1():                                                            #流图
    top1 = Toplevel()
    top1.title('流图')
    Label(top1, text='矩阵维数').grid(row=0, column=0)              #矩阵维数标签
    lwei = StringVar()
    llwei = Entry(top1,textvariable = lwei)                         #矩阵维数文本框
    llwei.grid(row=0, column=1,  columnspan=2)
    Label(top1, text='矩阵：').grid(row=1,column=0)                 #矩阵标签
    lju = StringVar()
    llju = Entry(top1,textvariable = lju)                           #矩阵多行文本框
    llju.grid(row=1, column=1, columnspan=2)
    def liutu():
        def jiantou():
            tt.right(30)
            tt.backward(10)
            tt.forward(10)
            tt.left(60)
            tt.backward(10)
            tt.forward(10)
            tt.right(30)

        def draw(n, list):
            tt.penup()
            tt.goto(-200, 0)
            tt.pendown()
            tt.write('e(t)')
            tt.dot()
            tt.forward(50)
            tt.write('1')
            tt.forward(50)
            jiantou()
            tt.dot(10)
            if n % 2 == 1 and n != 1:
                an_div = 90 / ((n//2) + 1)
            elif n == 1:
                an_div = 0
            else:
                an_div = 90 / n
            for k in range(1, n + 1):
                tt.goto(-100, 0)
                tt.pendown()
                tt.setheading(0)
                if n % 2 == 1:
                    if k % 2 == 1:
                        temp = 1
                    else:
                        temp = -1
                    angle = k // 2 * an_div * temp
                    tt.left(angle)
                    tt.forward(50 / cos(angle * pi / 180))
                    tt.write(list[k - 1][1])
                    jiantou()
                    tt.forward(50 / cos(angle * pi / 180))
                    tt.dot(10)
                    tt.right(angle)
                    tt.forward(30)
                    tt.write('1/p')
                    jiantou()
                    tt.forward(30)
                    tt.dot(10)
                    tt.right(90)
                    tt.circle(-25, 90)
                    jiantou()
                    tt.write('-' + list[k - 1][0])
                    tt.circle(-30, 81)
                    tt.setheading(0)
                    tt.forward(60)
                    tt.dot()
                    tt.right(angle)
                    tt.forward(50 / cos(angle * pi / 180))
                    jiantou()
                    tt.write('1')
                    tt.forward(50 / cos(angle * pi / 180))
                    tt.dot()
                    tt.setheading(0)
                    tt.forward(50)
                    jiantou()
                    tt.write('1')
                    tt.forward(50)
                if n % 2 == 0:
                    if k % 2 == 1:
                        temp = 1;
                        p = k + 1
                    else:
                        temp = -1;p = k
                    angle = p / 2 * an_div * temp
                    tt.left(angle)
                    tt.forward(50 / cos(angle * pi / 180))
                    tt.write(list[k - 1][1])
                    jiantou()
                    tt.forward(50 / cos(angle * pi / 180))
                    tt.dot(10)
                    tt.right(angle)
                    tt.forward(30)
                    tt.write('1/p')
                    jiantou()
                    tt.forward(30)
                    tt.dot(10)
                    tt.right(90)
                    tt.circle(-25, 90)
                    jiantou()
                    tt.write('-' + list[k - 1][0])
                    tt.circle(-30, 81)
                    tt.setheading(0)
                    tt.forward(60)
                    tt.dot()
                    tt.right(angle)
                    tt.forward(50 / cos(angle * pi / 180))
                    jiantou()
                    tt.write('1')
                    tt.forward(50 / cos(angle * pi / 180))
                    tt.dot()
                    tt.setheading(0)
                    tt.forward(50)
                    jiantou()
                    tt.write('1')
                    tt.forward(50)
                    tt.penup()
            tt.write('r(t)')
            tt.done()


        def main1():
            n = int(llwei.get())
            print(n)
            l = []
            list=llju.get().split(';')
            for m in range(n):
                l.append(list[m].split())
            draw(n, l)

        main1()
    Button(top1, text='确定', command= liutu).grid(row=2, column=2)


def b2():                                                            #可观可控性
    top2 = Toplevel()
    top2.title('可观可控性解决')
    Label(top2, text='矩阵维数').grid(row=0, column=0, sticky=N+S)              #矩阵维数标签
    cwei = StringVar()
    ccwei = Entry(top2,textvariable = cwei)
    ccwei.grid(row=0, column=1, columnspan=2, sticky=N+S)                       #矩阵维数文本框
    Label(top2, text='矩阵A').grid(row=1, column=0,sticky=N+S)                  #矩阵A标签
    cju = StringVar()
    ccju = Entry(top2, textvariable=cju)
    ccju.grid(row=1, column=1, columnspan=2, sticky=N+S)                         #矩阵A文本框
    Label(top2, text='矩阵B').grid(row=2, column=0, sticky=N+S)                  #矩阵B标签
    cjub = StringVar()
    ccjub = Entry(top2, textvariable=cjub)
    ccjub.grid(row=2, column=1, columnspan=2, sticky=N+S)                        #矩阵B文本框
    Label(top2, text='矩阵C').grid(row=3, column=0, sticky=N+S)                  #矩阵C文本框
    cjuc = StringVar()
    ccjuc = Entry(top2, textvariable=cjuc)
    ccjuc.grid(row=3, column=1, columnspan=2, sticky=N+S)                        #矩阵C文本框
    def con1():                                                      #可观可控性处理函数
        n = int(ccwei.get())
        lst1 = [];lst2 = []
        str1 = ccju.get().split(';')
        str2 = ccjub.get().split(';')
        str3 = ccjuc.get()
        for i in range(n):
            lst1.append(list(map(int, str1[i].split())))
        for j in range(n):
            lst2.append(list(map(int, str2[j])))
        A = np.array(lst1)
        B = np.array(lst2)
        M = B
        for k in range(1, n):
            B = np.matmul(A, B)  # 矩阵相乘
            M = np.insert(M, k, values=B.T, axis=1)
        d = np.linalg.matrix_rank(M)  # 返回矩阵的秩

        # 可观性
        lst3 = []
        lst3.append(list(map(int, str3.split(','))))
        C = np.array(lst3)
        print(C)
        ARR = C
        for k in range(1, n):
            C = np.matmul(C, A)
            ARR = np.insert(ARR, k, values=C, axis=0)
        e = np.linalg.matrix_rank(M)  # 返回矩阵的秩

        print(M)
        print(ARR)

        if d < n:
            jieguo1='系统不完全可控'
        else:
            jieguo1='系统可控'
        if e < n:
            jieguo2='系统不完全可观'
        else:
            jieguo2='系统可观'
        t1.insert("insert",jieguo1+'\r\n'+jieguo2)
    Button(top2, text='确定', command = con1).grid(row=4, column=0,columnspan=4,sticky=N+E+W)
    t1 = Text(top2, height=7)
    t1.grid(row=0,column=3,rowspan=5,sticky=N+E+W)
def b3():                                                            #零输入条件解状态方程
    top3 = Toplevel()
def b4():                                                            #自然频率与稳定性
    top4 = Toplevel()
    top4.title('自然频率与稳定性')
    Label(top4, text='矩阵维数').grid(row=0, column=0, sticky=N+S)               #矩阵维数标签
    weishu = StringVar()
    fweishu = Entry(top4,textvariable = weishu)
    fweishu.grid(row=0, column=1, columnspan=2,  sticky=N+S)                      #矩阵维数文本框
    Label(top4, text='矩阵A').grid(row=1, column=0, sticky=N+S)                  #矩阵A标签
    juzhen = StringVar()
    fjuzhen = Entry(top4,textvariable = juzhen)
    fjuzhen.grid(row=1, column=1, columnspan=2,  sticky=N+S)                     #矩阵A文本框
    def fe():
        z = sy.Symbol('Z')
        n = int(fweishu.get())
        juzhen = []
        flag = 0
        str4 = fjuzhen.get().split(';')
        for i in range(n):
            juzhen.append(str4[i].split())
        m = sy.Matrix(juzhen)
        m1 = sy.eye(n)
        m2 = z * m1 - m
        delta = m2.det()  # 行列式表达式
        value = sy.solve(delta, z)
        length = len(value)
        print('自然频率为：', value)
        for j in range(length):
            if complex(value[j]).real < 1 and complex(value[j]).imag<1:
                continue
            else:
                flag = 1
                break
        if flag == 0:
            shuchu = '该系统稳定'
        elif flag == 1:
            shuchu = '该系统不稳定'
        t4.insert("insert",'自然频率为：'+str(value)+shuchu)
    Button(top4, text='确定', command = fe).grid(row=2, column=0, columnspan = 5, sticky=N+E+W)
    t4 = Text(top4,height = 5)
    t4.grid(row=0,column=3, columnspan=2, rowspan=2)
def b5():                                                            #微分方程
    top5 = Toplevel()
    top5.title('微分方程')
    Label(top5, text='二阶微分方程').grid(row=0, column=0,columnspan=5, sticky=N+E+W)#标题
    Label(top5, text='a:').grid(row=1, column=0)#参数a的标签
    ca = StringVar()
    wca = Entry(top5,textvariable = ca)
    wca.grid(row=1, column=1, columnspan=2)#参数a的文本框
    Label(top5, text='b:').grid(row=2, column=0)#参数b的标签
    cb = StringVar()
    wcb = Entry(top5,textvariable = cb)
    wcb.grid(row=2, column=1, columnspan=2)#参数b的文本框
    Label(top5, text='p(x):').grid(row=3, column=0)#参数p(x)的标签
    cpx = StringVar()
    wcpx = Entry(top5,textvariable = cpx)
    wcpx.grid(row=3, column=1, columnspan=2)#参数p(x)的文本框
    Label(top5, text='q(x):').grid(row=4, column=0)#参数q(x)的标签
    cqx = StringVar()
    wcqx = Entry(top5,textvariable = cqx)
    wcqx.grid(row=4, column=1, columnspan=2)#参数q(x)的文本框
    def de():#微分方程处理函数
        a = wca.get()
        b = wcb.get()
        px = wcpx.get()
        qx = wcqx.get()

        def differential_equation(x, f):
            return eval(a) * sy.diff(f(x), x, 2) + eval(b) *sy.diff(f(x), x, 1) + eval(px) * f(x) - eval(
                qx)  # f(x)''+f(x)=0 二阶常系数齐次微分方程

        x = sy.symbols('x')  # 约定变量
        f = sy.Function('f')  # 约定函数
        fxtemp = str(sy.dsolve(differential_equation(x, f), f(x))).split(',')[1]
        lst1 = list(fxtemp)
        del lst1[-1]  # 去掉不必要的')'
        fx = ''.join(lst1)
        print('fx=', fx)  # 打印
        sy.pprint(sy.dsolve(differential_equation(x, f), f(x)))  # 漂亮的打印
        t5.insert("insert",fx)
    Button(top5, text='确定',command = de).grid(row=5, column=0, columnspan=5, sticky=N+E+W)#确定按钮
    t5 = Text(top5,height=7)
    t5.grid(row=1, column=3, columnspan=2, rowspan=4)
#主窗口内容
Label(C12,text="选题").pack()                                            #定义标签
Button(C12,text="流图",width=30,command=b1).pack()                       #第一个按钮
Button(C12,text="可观可控性",width=30,command=b2).pack()                 #第二个按钮
#Button(C12,text="零输入条件解状态方程",width=30,command=b3).pack()       #第三个按钮
Button(C12,text="自然频率与稳定性",width=30,command=b4).pack()           #第四个按钮
Button(C12,text="微分方程",width=30,command=b5).pack()                   #第五个按钮
C12.mainloop()
